package com.yuanduo_app.manager;

import android.annotation.SuppressLint;

import com.google.common.util.concurrent.ListenableFuture;
import com.xujl.fastlib.utils.ConfigManager;
import com.xujl.task.RxExecutor;
import com.xujl.task.Task;

import com.yuanduo_app.consts.FileConst;
import com.yuanduo_app.widget.CameraXCustomPreviewView;

import java.io.File;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.FocusMeteringAction;
import androidx.camera.core.FocusMeteringResult;
import androidx.camera.core.MeteringPoint;
import androidx.camera.core.MeteringPointFactory;
import androidx.camera.core.Preview;
import androidx.camera.core.VideoCapture;
import androidx.camera.core.ZoomState;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;


public class RecorderManager {
    private ExecutorService cameraExecutor;
    private ProcessCameraProvider cameraProvider;//相机信息
    private Preview preview;//预览对象
    private CameraSelector cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA;//当前相机
    private Camera camera;
    private VideoCapture videoCapture;
    private CameraXCustomPreviewView viewFinder;
    private String videoPath = FileConst.RECORD + FileConst.RECORD_CACHE;

    public void init () {
    }

    public void bindView (CameraXCustomPreviewView viewFinder) {
        this.viewFinder = viewFinder;
    }


    public void startCamera (LifecycleOwner lifecycle) {
        cameraExecutor = Executors.newSingleThreadExecutor();
        final ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(ConfigManager.getInstance().getContext());
        cameraProviderFuture.addListener(new Runnable() {
            @Override
            public void run () {
                try {
                    cameraProvider = cameraProviderFuture.get();//获取相机信息
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //预览配置
                preview = new Preview.Builder()
                        .build();
                preview.setSurfaceProvider(viewFinder.createSurfaceProvider());

                videoCapture = new VideoCapture.Builder().build();//录像用例配置
                cameraProvider.unbindAll();//先解绑所有用例
                camera = cameraProvider.bindToLifecycle(lifecycle, cameraSelector, preview, videoCapture);//绑定用例
                initCameraListener();
            }
        }, ContextCompat.getMainExecutor(ConfigManager.getInstance().getContext()));
    }

    private void initCameraListener () {
        LiveData<ZoomState> zoomState = camera.getCameraInfo().getZoomState();
        viewFinder.setCustomTouchListener(new CameraXCustomPreviewView.CustomTouchListener() {
            @Override
            public void zoom (float delta) {
                //双指缩放
                ZoomState state = zoomState.getValue();
                camera.getCameraControl().setZoomRatio(state.getZoomRatio() * delta);
            }

            @Override
            public void click (float x, float y) {
                //点击对焦
                if (cameraSelector == CameraSelector.DEFAULT_BACK_CAMERA) {
                    MeteringPointFactory factory = viewFinder.createMeteringPointFactory(cameraSelector);
                    MeteringPoint point = factory.createPoint(x, y);
                    FocusMeteringAction action = new FocusMeteringAction.Builder(point, FocusMeteringAction.FLAG_AF)
                            .setAutoCancelDuration(3, TimeUnit.SECONDS)
                            .build();
                    final ListenableFuture<FocusMeteringResult> future = camera.
                            getCameraControl().startFocusAndMetering(action);
                    future.addListener(new Runnable() {
                        @Override
                        public void run () {
                            //对焦是否成功
                            FocusMeteringResult result = null;
                            try {
                                result = future.get();
                            } catch (ExecutionException e) {
                                e.printStackTrace();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            if (result.isFocusSuccessful()) {
                            } else {
                            }
                        }
                    }, cameraExecutor);
                }
            }

            @Override
            public void doubleClick (float x, float y) {
                //双击放大缩小
                final float currentZoomRatio = zoomState.getValue().getZoomRatio();
                if (currentZoomRatio > zoomState.getValue().getMinZoomRatio()) {
                    camera.getCameraControl().setLinearZoom(0f);
                } else {
                    camera.getCameraControl().setLinearZoom(0.5f);
                }
            }

            @Override
            public void longClick (float x, float y) {

            }
        });
    }


    @SuppressLint("RestrictedApi")
    public void takeVideo (VideoCapture.OnVideoSavedCallback callback) {
        //视频保存路径
        File file = new File(videoPath);
        //开始录像
        videoCapture.startRecording(file, Executors.newSingleThreadExecutor(), new
                VideoCapture.OnVideoSavedCallback() {
                    @Override
                    public void onVideoSaved (@NonNull File file) {
                        RxExecutor.getInstance()
                                .executeUiTask(new Task() {
                                    @Override
                                    public void onlyRunUiTask () {
                                        super.onlyRunUiTask();
                                        if (callback != null) {
                                            callback.onVideoSaved(file);
                                        }
                                    }
                                });
                    }

                    @Override
                    public void onError (int videoCaptureError, @NonNull String message, @Nullable Throwable cause) {
                        RxExecutor.getInstance()
                                .executeUiTask(new Task() {
                                    @Override
                                    public void onlyRunUiTask () {
                                        super.onlyRunUiTask();
                                        if (callback != null) {
                                            callback.onError(videoCaptureError, message, cause);
                                        }
                                    }
                                });
                    }

                });

    }

    @SuppressLint("RestrictedApi")
    public void stopTakeVideo () {
        videoCapture.stopRecording();//停止录制
        preview.clear();//清除预览
    }

    @SuppressLint("RestrictedApi")
    public void recycle () {
        if (cameraExecutor != null) {
            cameraExecutor.shutdown();
        }

        if (videoCapture != null) {
            stopTakeVideo();
        }
        if (cameraProvider != null) {
            cameraProvider.unbindAll();
        }

    }
}
